extends layout

block append style
  link(rel="stylesheet" href="/docs/css/flexcpc.css")
  script(type="text/javascript" src="/docs/js/native.js")

block content
  :markdown
    # Testing Mongoose with [Jest](https://www.npmjs.com/package/jest)

    Jest is a client-side JavaScript testing library developed by Facebook.
    It was one of the libraries affected by [Facebook's licensing scandal in 2017](https://www.theregister.co.uk/2017/09/22/facebook_will_free_react_other_code_from_unloved_license/).
    Because Jest is designed primarily for testing React applications, using
    it to test Node.js server-side applications comes with a lot of caveats.
    We strongly recommend using [Mocha](http://npmjs.com/package/mocha) instead.
    If you choose to delve into dangerous waters and test Mongoose apps with
    Jest, here's what you need to know:

    ## Recommended `testEnvironment`

    Do **not** use Jest's default [`jsdom` test environment](https://jestjs.io/docs/en/configuration.html#testenvironment-string)
    when testing Mongoose apps, _unless_ you are explicitly testing an
    application that only uses
    [Mongoose's browser library](https://mongoosejs.com/docs/browser.html).

    The `jsdom` test environment attempts to create a browser-like test
    environment in Node.js, and it comes with numerous nasty surprises like a
    [stubbed `setTimeout()` function](https://github.com/jsdom/jsdom/commit/3f306bea5362aceb2a219a2e98ff96a7464d2f19#commitcomment-31316213)
    that silently fails after tests are finished. Mongoose does not support jsdom
    in general and is not expected to function correctly in the `jsdom` test
    environment.

    To change your `testEnvironment` to Node.js, add `testEnvironment` to your
    `jest.config.js` file:

    ```javascript
    module.exports = {
      testEnvironment: 'node'
    };
    ```

    ## Timer Mocks

    Absolutely do **not** use [timer mocks](https://jestjs.io/docs/en/timer-mocks.html)
    when testing Mongoose apps. Mongoose devs have already refactored out code
    to [avoid using `setImmediate()`](https://github.com/Automattic/mongoose/issues/6074)
    to defer work to the next tick of the event loop, but we can't reasonably
    ensure that every library Mongoose depends on doesn't use `setImmediate()`.
    
    Mongoose uses `nextTick()`, which [Jest's underlying dependency explicitly doesn't stub by default](https://sinonjs.org/releases/latest/fake-timers/).
    But, `process.nextTick()` isn't the same as `setImmediate()` because of
    [microtasks vs macrotasks](https://abc.danch.me/microtasks-macrotasks-more-on-the-event-loop-881557d7af6f#2261),
    so underlying libraries like the [MongoDB driver](http://npmjs.com/package/mongodb) may use `setImmediate()`.

    To work around this, create your own wrapper around `setTimeout()` and
    stub that instead using [sinon](http://npmjs.com/package/sinon).

    ```javascript
    // time.js
    exports.setTimeout = function() {
      return global.setTimeout.apply(global, arguments);
    };

    // Tests
    const time = require('../util/time');
    const sinon = require('sinon');
    sinon.stub(time, 'setTimeout');
    ```

block append layout
  script.
    _native.init("CK7DT53U", {
      targetClass: 'native-js',
      display: 'flex',
      visibleClass: 'native-show'
    });

  div(class="native-js").
    <div class="native-sponsor">Sponsored by #native_company# — Learn More</div>
    <a href="#native_link#" class="native-flex">
      <style>
      .native-js {
        background: linear-gradient(-30deg, #native_bg_color#E5, #native_bg_color#E5 45%, #native_bg_color# 45%) #fff;
      }

      .native-details,
      .native-sponsor,
      .native-bsa {
        color: #native_color# !important;
      }

      .native-details:hover {
        color: #native_color_hover# !important;
      }

      .native-cta {
        color: #native_cta_color#;
        background-color: #native_cta_bg_color#;
      }

      .native-cta:hover {
        color: #native_cta_color_hover;
        background-color: #native_cta_bg_color_hover#;
      }
      </style>
      <div class="native-main">
        <img class="native-img" src="#native_logo#">
        <div class="native-details">
          <span class="native-company">#native_title#</span>
          <span class="native-desc">#native_desc#</span>
        </div>
      </div>
      <span class="native-cta">#native_cta#</span>
    </a>
